Skip to content

几个角度规范项目开发

  1. eslint 对js、ts以及在vue项目中的js代码进行质量和风格的检查。
  2. stylelint 对css代码,包括sass,less等代码的风格和质量进行检查。
  3. prettier 专注于对代码风格的修复,可以结果上面两个插件对代码进行自动修复。
  4. editorconfig用于编辑器的默认行为,比如新建一个文件、新起一行、一个tab键的默认格式等。
  5. .gitconfig 用于配置当前项目git的默认行为,比如下载的代码是lf还是crlf(mac和windows同学最对碰到的问题),如果使用个人电脑,需要不同的项目对应不同user.name 等需要配置。.git/config文件。
  6. cz工具能够对commit信息进行编辑。
  7. husky通过对git add、commit和publish过程的介入,对项目本地化规范。

eslint

eslint通过在项目根目录配置eslintrc.*文件。通过parse选项对文件进行分析。eslint 会从当前文件依次向上检查配置文件,直到文件系统根目录或则碰到一个root: true 的配置文件,利用这个可以给mono配置不同的配置检查,配置文件主要包含一下内容

  • env 和 globals 针对全局变量中的检查,比如window变量,document变量等,nodejs的__dirname等等。env 相当于globals的合集。
  • parse 和 parseOptions 解析器和解析器选项。 默认是esprima,可以配置成@babel/eslint-parser的 ,支持ts @typescript-eslint/parser 和 支持vue的eslint-plugin-vue。
  • rule 配置不同归的规则,key、value形式的对象。value 0 1 2 表示禁用,警告和错误。支持数组的形式调用。数组第二项是rule的参数。
  • extends,返回一个有config属性的对象。config属性对应的是配置文件,见后文如何提供一个eslint-plugin。extends都是由插件导入。
  • plugins 提供rules的解析,和extends的区别是plugin 提供的是rule规则,但是还未配置。所以一般使用plugin后需要配置相应的extend。plugin 还提供了processor 能力。
  • processor 是由plugin 提供,能对非js文件中的js片段提取进行eslint检查。一般都是对应Plugin的extend配置提供。
  • overrides 可以覆盖默认的配置,会和全局的定义的配置进行合并

eslint-plugin-vue https://eslint.vuejs.org/rules/

下面配置vue3 eslint为例

npm i -D eslint-plugin-vue

js
module.exports = {
    env: {
        node: true,
        browser: true
    },
    globals: [
        '__webpack_public__path__', // 忽略代码中webpack相关变量
    ]
    parse: 'vue-eslint-parse',  // 解析vue中template
    parseOptions: {
        parse: '@typescript-eslint/parse',
        sourceType: 'module'
        // ... 其余@typescript-eslint/parse parseOptions
    },
    plugins: [
        'vue'  // eslint会默认添加eslint-plugin-vue
        '@juqery/test',  // @juqery/eslint-plugin-test
        '@test'  // @test/eslint-plugin  @开头总是会处理成组织名
    ],
    extends: [
        'plugin:vue'  // 去eslint-plugin-vue 包中导入config对象
        'test',  // eslint-config-test包中导入   // 默认前缀是eslint-config
    ]
}

plugin浅解析

js
// 包 eslint-plugin-xunserver
module.exports = {
    rules: {
        'xxxx': () => {  // rule 定义
            create() {

            },
            meta() {

            }
        }
    }
    config: {
        vue3: { // 使用时先在plugin中添加rule定义  plugins: ['xunserver'], 然后extends: ['eslint-plugin-xunserver/vue3 或者eslint-plugin-xunserver/vue2']
            env: {
                node: true,
                browser: true,
            },
            extends: [
                'other config'
            ]
        },
        vue2: {
            // 大致同上
        }
    },
    processor: {
        // processor 对象
        'xxx': {

        }
    }
}

stylelint

stylelint 配置上同eslint类似。从当前文件开始依次向上寻找.stylelintrc.js配置文件,直到找到为止。同eslint区别是默认都是root配置。大致配置如下

  • customSynax,定义解析器,比如在vue和html中使用就需要配置,一般和override搭配使用
  • extends, 继承其他配置,可以实现插件和customSynax的引入,和eslint有区别,extends大部分时候还用来配置插件。配置在后面的覆盖前面的,extends引入的会被覆盖。
  • plugins,通过插件提供新的规则,一般插件只提供了规则,但是未配置,需要extends配置或者自行配置。
  • overrides 能针对不能的文件类型使用不同的配置规则。比如stylelint-config-html/vue 实现了vue的特殊处理。
  • rules 对不同的规则配置,null表示规则不生效,其余需要参考rule的实现,数组形式如果第二项是对象,则认为是第二参数。通用的参数有disableFix,message两个关注的。一个可以不处理fix,一个可以自定义报错信息。
  • ignoreFiles 忽略文件。第三库不使用stylelint

recss

Reasonable System css, 通过style-config-recss 实现规范

less sass 和 stylus 的解析

使用别人配置好的stylelint-config-standard、stylelint-config-standard-xx 实现,其中stylelint-config-standard是在 stylelint-config-recommend 基础上实现。

如果是自行配置需要,overrides 对应的less、scss和stylus文件,解析器是postcss-less postcss-scss 和 postcss-styl

vue需要安装postcss-html 和对应的postcss-less postcss-scss 等

解决prettier冲突

同理stylelint不解决格式上的问题,需要关闭和prettier冲突的rules。

实现一个extend

js
modules.exports = {
    extends: ['others extends'],
    overrides: [
        {
            file: ['*.vue', '**/*.vue'],
            customSynax: 'postcss-html'
        }
    ]
}

prettier

prettier 是一个format工具,eslint和stylelint同时具有lint和format功能,执行顺序是eslint => prettier 或者stylelint => prettier。 prettier 的配置文件比较简单,一共就10多个选项,使用时指定需要使用的文件即可,prettier在项目中使用意义不大,主要是不能在codeActionSave中使用。目前prettier对css 和 js的格式化都交给对应的格式化工具,不够prettier 对其他语法的格式化还是比较好用,还是建议在编辑保留。 prettier还会使用editorconfig中的配置来初始化配置,如果新建文件总是报错飘红,建议检查editorconfig 和 prettier中冲突的部分。

vscode中引入格式化工具

vscode 区分为工作区和用户区配置(本地和全局),vscode提供了两种format方式,一种是codeActionOnSave,表示保存时调用格式化工具。另一个是defaultEditor: 'xxx', 表示使用快捷键格式化时调用的工具。

  • codeActionOnSave和formatOnSave, formateOnSave是defaultEditor在保存时调用的方式,现在基本启用。codeActionOnSave支持多个格式化程序依次调用。vscode插件在初始化时会向vscode注册format功能

vscode针对不同类型的文件能够采用不同的配置,"[html]"为html类型的文件采用特定的配置。

vue中template如何格式化

vue中template中规范prop能够保证良好的编码思路。建议加上vue/attributes-order。

husky、lint-stage、commitizen和cz-customizable

  • husky 用于在git的各种阶段执行脚本,如果脚本返回错误,停止流程。
  • list-stage 用于只校验暂存区文件,提高lint速度,在校验文件时,会从文件的当前的目录开始查找最近的配置,在根目录配置baseconfig,子目录继承。
  • commitizen是一个检查commit message的工具。支持各种adapter。cz-customizable 是对应的adapter。安装好后使用git-cz代替git commit。该方案不能很好的和vscode结合,不采用。
  • commitlint 检查commit msg是否合规,结合husky实现commit信息的校验。

husky安装配置

pnpm add husky -Dw // 项目安装在根目录 pnpm set-script prepare "husky install" 配置package.json script.prepare 脚本 pnpm husky install // 初始化husky pnpm add './husky/pre-commit' 'lint-stage' // 不同包调用自身的lint-stage 方法 pnpm add './husky/pre-push' 'pnpm -F "./packages/**" run lint' // 全局校验

list-stage

在子项目中单独配置.lintstagedrc.js文件,文件内容如下。

js
// .lintstagedrc.js
const baseConfig = require('../../.lintstagedrc.js')
module.exports = {
    ...baseConfig,
    '*.{js,jsx,ts,tsx.vue,html}': ['eslint --config .eslintrc.js'],
    '*.{css,scss,sass,less,styl,vue,html}': ['stylelint --config .stylelintrc.js']
    '*.{ts,tsx,js,jsx,json,html,yml,css,less,scss,md,sass}': ['prettier --write']
}

commitlint

pnpm add commitlint -Dw pnpm husky add './hasky/commit-msg' 'pnpm commitlint --config .commitlintrc.js --edit $1' 添加.commitlintrc.js文件

js
/**
 * build : 改变了build工具 如 webpack
 * ci : 持续集成新增
 * chore : 构建过程或辅助工具的变动
 * feat : 新功能
 * docs : 文档改变
 * fix : 修复bug
 * perf : 性能优化
 * refactor : 某个已有功能重构
 * revert : 撤销上一次的 commit
 * style : 代码格式改变
 * test : 增加测试
 * anno: 增加注释
 */

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
      2,
      'always',
      [
        'build',
        'ci',
        'chore',
        'docs',
        'feat',
        'fix',
        'perf',
        'refactor',
        'revert',
        'style',
        'test',
        'anno',
      ],
    ],
  },
};

eslintrc.js和eslintignore 文件

eslint(stylelint)在执行时,按照如下执行。

  1. 确定当前使用的eslint文件位置,确定执行的上下文。
  2. 确定需要处理的全部文件
  3. 根据上下文中中的.eslitingnore、命令中的--no-ignore、--ext 确定需要处理的最终文件合集
  4. 一个一个文件的查找eslintrc配置,找到配置后执行eslint。配置的查找规则从当前需要检查的配置往上级目录查找,知道文件系统的根目录或者碰到一个root:true的配置文件,这种方式相当于变相实现了继承(stylelint在查找到第一个配置文件后停止,意味着需要自行实现继承)。

vscode中eslint和stylelint

vscode执行逻辑大致同上,只是确定文件的方式有所不同。

  1. vscode打开时加载项目根目录下的ignore文件
  2. 根据vscode中的no-ignore 和插件配置的生效文件确定最终文件。

lint-staged 如何实现只检查部分文件

eslint,styllint和prettier均支持stdin方式确定输入文件。lint-staged把需要检查的文件和配置一一对比,确定出需要执行命令的文件,添加在命令后。 lintstagedrc的查找方式从被检查的文件开始向上查找,lintstagedrc中指令执行的上下和本身相同

js
// lintstagedrc.js
module.exports = {
    "*.(vue,ts,tsx,js,jsx)": "eslint"   // 相当于执行在.lintstagedrc.js所在目录下执行eslint xx.js命令
}

monorepo格式化解决方案

monorepo仓库有如下难点需要解决。

  1. 不同项目使用不同技术栈,采用的规范不一致。
  2. CI和lint-staged中的校验是全局的。
  3. vscode编辑器总是从项目根目录读取工具并加载ignore文件。 针对以上问题,解决方案如下
  4. 不同的子项目在编码时,建议到对应的子目录下编写,目的是为了匹配vscode的格式化功能。
  5. 不同子项目在配置时,通通引用公共的配置
  6. ci和git 校验时采用调用各子项目中的lint工具。